home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Mail / mime.php < prev    next >
PHP Script  |  2004-03-24  |  24KB  |  653 lines

  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Copyright (c) 2002  Richard Heyes                                     |
  4. // | All rights reserved.                                                  |
  5. // |                                                                       |
  6. // | Redistribution and use in source and binary forms, with or without    |
  7. // | modification, are permitted provided that the following conditions    |
  8. // | are met:                                                              |
  9. // |                                                                       |
  10. // | o Redistributions of source code must retain the above copyright      |
  11. // |   notice, this list of conditions and the following disclaimer.       |
  12. // | o Redistributions in binary form must reproduce the above copyright   |
  13. // |   notice, this list of conditions and the following disclaimer in the |
  14. // |   documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote      |
  16. // |   products derived from this software without specific prior written  |
  17. // |   permission.                                                         |
  18. // |                                                                       |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
  30. // |                                                                       |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@phpguru.org>                           |
  33. // |         Tomas V.V.Cox <cox@idecnet.com> (port to PEAR)                |
  34. // +-----------------------------------------------------------------------+
  35. //
  36. // $Id: mime.php,v 1.23 2002/07/27 14:37:53 richard Exp $
  37.  
  38. require_once 'PEAR.php';
  39. require_once 'Mail/mimePart.php';
  40.  
  41. /**
  42. * Mime mail composer class. Can handle: text and html bodies, embedded html
  43. * images and attachments.
  44. * Documentation and examples of this class are avaible here:
  45. * http://pear.php.net/manual/
  46. *
  47. * @notes This class is based on HTML Mime Mail class from
  48. *   Richard Heyes <richard@phpguru.org> which was based also
  49. *   in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it> and
  50. *   Sascha Schumann <sascha@schumann.cx>.
  51. *
  52. * @author Richard Heyes <richard.heyes@heyes-computing.net>
  53. * @author Tomas V.V.Cox <cox@idecnet.com>
  54. * @package Mail
  55. * @access public
  56. */
  57. class Mail_mime
  58. {
  59.     /**
  60.     * Contains the plain text part of the email
  61.     * @var string
  62.     */
  63.     var $_txtbody;
  64.     /**
  65.     * Contains the html part of the email
  66.     * @var string
  67.     */
  68.     var $_htmlbody;
  69.     /**
  70.     * contains the mime encoded text
  71.     * @var string
  72.     */
  73.     var $_mime;
  74.     /**
  75.     * contains the multipart content
  76.     * @var string
  77.     */
  78.     var $_multipart;
  79.     /**
  80.     * list of the attached images
  81.     * @var array
  82.     */
  83.     var $_html_images = array();
  84.     /**
  85.     * list of the attachements
  86.     * @var array
  87.     */
  88.     var $_parts = array();
  89.     /**
  90.     * Build parameters
  91.     * @var array
  92.     */
  93.     var $_build_params = array();
  94.     /**
  95.     * Headers for the mail
  96.     * @var array
  97.     */
  98.     var $_headers = array();
  99.  
  100.  
  101.     /*
  102.     * Constructor function
  103.     *
  104.     * @access public
  105.     */
  106.     function Mail_mime($crlf = "\r\n")
  107.     {
  108.         if (!defined('MAIL_MIME_CRLF')) {
  109.             define('MAIL_MIME_CRLF', $crlf, true);
  110.         }
  111.  
  112.         $this->_boundary = '=_' . md5(uniqid(time()));
  113.  
  114.         $this->_build_params = array(
  115.                                      'text_encoding' => '7bit',
  116.                                      'html_encoding' => 'quoted-printable',
  117.                                      '7bit_wrap'     => 998,
  118.                                      'html_charset'  => 'ISO-8859-1',
  119.                                      'text_charset'  => 'ISO-8859-1',
  120.                                      'head_charset'  => 'ISO-8859-1'
  121.                                     );
  122.     }
  123.  
  124.     /*
  125.     * Accessor function to set the body text. Body text is used if
  126.     * it's not an html mail being sent or else is used to fill the
  127.     * text/plain part that emails clients who don't support
  128.     * html should show.
  129.     *
  130.     * @param string $data Either a string or the file name with the
  131.     *        contents
  132.     * @param bool $isfile If true the first param should be trated
  133.     *        as a file name, else as a string (default)
  134.     * @param bool If true the text or file is appended to the
  135.     *        existing body, else the old body is overwritten
  136.     * @return mixed true on success or PEAR_Error object
  137.     * @access public
  138.     */
  139.     function setTXTBody($data, $isfile = false, $append = false)
  140.     {
  141.         if (!$isfile) {
  142.             if (!$append) {
  143.                 $this->_txtbody = $data;
  144.             } else {
  145.                 $this->_txtbody .= $data;
  146.             }
  147.         } else {
  148.             $cont = $this->_file2str($data);
  149.             if (PEAR::isError($cont)) {
  150.                 return $cont;
  151.             }
  152.             if (!$append) {
  153.                  $this->_txtbody = $cont;
  154.              } else {
  155.                  $this->_txtbody .= $cont;
  156.              }
  157.         }
  158.         return true;
  159.     }
  160.  
  161.     /*
  162.     * Adds a html part to the mail
  163.     *
  164.     * @param string $data Either a string or the file name with the
  165.     *        contents
  166.     * @param bool $isfile If true the first param should be trated
  167.     *        as a file name, else as a string (default)
  168.     * @return mixed true on success or PEAR_Error object
  169.     * @access public
  170.     */
  171.     function setHTMLBody($data, $isfile = false)
  172.     {
  173.         if (!$isfile) {
  174.             $this->_htmlbody = $data;
  175.         } else {
  176.             $cont = $this->_file2str($data);
  177.             if (PEAR::isError($cont)) {
  178.                 return $cont;
  179.             }
  180.             $this->_htmlbody = $cont;
  181.         }
  182.  
  183.         return true;
  184.     }
  185.  
  186.     /*
  187.     * Adds an image to the list of embedded images.
  188.     *
  189.     * @param string $file The image file name OR image data itself
  190.     * @param string $c_type The content type
  191.     * @param string $name The filename of the image. Only use if $file is the image data
  192.     * @param bool $isfilename Whether $file is a filename or not. Defaults to true
  193.     * @return mixed true on success or PEAR_Error object
  194.     * @access public
  195.     */
  196.     function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true)
  197.     {
  198.         $filedata = ($isfilename === true) ? $this->_file2str($file) : $file;
  199.         $filename = ($isfilename === true) ? basename($file) : basename($name);
  200.         if (PEAR::isError($filedata)) {
  201.             return $filedata;
  202.         }
  203.         $this->_html_images[] = array(
  204.                                       'body'   => $filedata,
  205.                                       'name'   => $filename,
  206.                                       'c_type' => $c_type,
  207.                                       'cid'    => md5(uniqid(time()))
  208.                                      );
  209.         return true;
  210.     }
  211.  
  212.     /*
  213.     * Adds a file to the list of attachments.
  214.     *
  215.     * @param string $file The file name of the file to attach OR the file data itself
  216.     * @param string $c_type The content type
  217.     * @param string $name The filename of the attachment. Only use if $file is the file data
  218.     * @param bool $isFilename Whether $file is a filename or not. Defaults to true
  219.     * @return mixed true on success or PEAR_Error object
  220.     * @access public
  221.     */
  222.     function addAttachment($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $encoding = 'base64')
  223.     {
  224.         $filedata = ($isfilename === true) ? $this->_file2str($file) : $file;
  225.         if ($isfilename === true) {
  226.             // Force the name the user supplied, otherwise use $file
  227.             $filename = (!empty($name)) ? $name : $file;
  228.         } else {
  229.             $filename = $name;
  230.         }
  231.         if (empty($filename)) {
  232.             return PEAR::raiseError('The supplied filename for the attachment can\'t be empty');
  233.         }
  234.         $filename = basename($filename);
  235.         if (PEAR::isError($filedata)) {
  236.             return $filedata;
  237.         }
  238.  
  239.         $this->_parts[] = array(
  240.                                 'body'     => $filedata,
  241.                                 'name'     => $filename,
  242.                                 'c_type'   => $c_type,
  243.                                 'encoding' => $encoding
  244.                                );
  245.         return true;
  246.     }
  247.  
  248.     /*
  249.     * Returns the contents of the given file name as string
  250.     * @param string $file_name
  251.     * @return string
  252.     * @acces private
  253.     */
  254.     function & _file2str($file_name)
  255.     {
  256.         if (!is_readable($file_name)) {
  257.             return PEAR::raiseError('File is not readable ' . $file_name);
  258.         }
  259.         if (!$fd = fopen($file_name, 'rb')) {
  260.             return PEAR::raiseError('Could not open ' . $file_name);
  261.         }
  262.         $cont = fread($fd, filesize($file_name));
  263.         fclose($fd);
  264.         return $cont;
  265.     }
  266.  
  267.     /*
  268.     * Adds a text subpart to the mimePart object and
  269.     * returns it during the build process.
  270.     *
  271.     * @param mixed    The object to add the part to, or
  272.     *                 null if a new object is to be created.
  273.     * @param string   The text to add.
  274.     * @return object  The text mimePart object
  275.     * @access private
  276.     */
  277.     function &_addTextPart(&$obj, $text){
  278.  
  279.         $params['content_type'] = 'text/plain';
  280.         $params['encoding']     = $this->_build_params['text_encoding'];
  281.         $params['charset']      = $this->_build_params['text_charset'];
  282.         if (is_object($obj)) {
  283.             return $obj->addSubpart($text, $params);
  284.         } else {
  285.             return new Mail_mimePart($text, $params);
  286.         }
  287.     }
  288.  
  289.     /*
  290.     * Adds a html subpart to the mimePart object and
  291.     * returns it during the build process.
  292.     *
  293.     * @param mixed    The object to add the part to, or
  294.     *                 null if a new object is to be created.
  295.     * @return object  The html mimePart object
  296.     * @access private
  297.     */
  298.     function &_addHtmlPart(&$obj){
  299.  
  300.         $params['content_type'] = 'text/html';
  301.         $params['encoding']     = $this->_build_params['html_encoding'];
  302.         $params['charset']      = $this->_build_params['html_charset'];
  303.         if (is_object($obj)) {
  304.             return $obj->addSubpart($this->_htmlbody, $params);
  305.         } else {
  306.             return new Mail_mimePart($this->_htmlbody, $params);
  307.         }
  308.     }
  309.  
  310.     /*
  311.     * Creates a new mimePart object, using multipart/mixed as
  312.     * the initial content-type and returns it during the
  313.     * build process.
  314.     *
  315.     * @return object  The multipart/mixed mimePart object
  316.     * @access private
  317.     */
  318.     function &_addMixedPart(){
  319.  
  320.         $params['content_type'] = 'multipart/mixed';
  321.         return new Mail_mimePart('', $params);
  322.     }
  323.  
  324.     /*
  325.     * Adds a multipart/alternative part to a mimePart
  326.     * object, (or creates one), and returns it  during
  327.     * the build process.
  328.     *
  329.     * @param mixed    The object to add the part to, or
  330.     *                 null if a new object is to be created.
  331.     * @return object  The multipart/mixed mimePart object
  332.     * @access private
  333.     */
  334.     function &_addAlternativePart(&$obj){
  335.  
  336.         $params['content_type'] = 'multipart/alternative';
  337.         if (is_object($obj)) {
  338.             return $obj->addSubpart('', $params);
  339.         } else {
  340.             return new Mail_mimePart('', $params);
  341.         }
  342.     }
  343.  
  344.     /*
  345.     * Adds a multipart/related part to a mimePart
  346.     * object, (or creates one), and returns it  during
  347.     * the build process.
  348.     *
  349.     * @param mixed    The object to add the part to, or
  350.     *                 null if a new object is to be created.
  351.     * @return object  The multipart/mixed mimePart object
  352.     * @access private
  353.     */
  354.     function &_addRelatedPart(&$obj){
  355.  
  356.         $params['content_type'] = 'multipart/related';
  357.         if (is_object($obj)) {
  358.             return $obj->addSubpart('', $params);
  359.         } else {
  360.             return new Mail_mimePart('', $params);
  361.         }
  362.     }
  363.  
  364.     /*
  365.     * Adds an html image subpart to a mimePart object
  366.     * and returns it during the build process.
  367.     *
  368.     * @param  object  The mimePart to add the image to
  369.     * @param  array   The image information
  370.     * @return object  The image mimePart object
  371.     * @access private
  372.     */
  373.     function &_addHtmlImagePart(&$obj, $value){
  374.  
  375.         $params['content_type'] = $value['c_type'];
  376.         $params['encoding']     = 'base64';
  377.         $params['disposition']  = 'inline';
  378.         $params['dfilename']    = $value['name'];
  379.         $params['cid']          = $value['cid'];
  380.         $obj->addSubpart($value['body'], $params);
  381.     }
  382.  
  383.     /*
  384.     * Adds an attachment subpart to a mimePart object
  385.     * and returns it during the build process.
  386.     *
  387.     * @param  object  The mimePart to add the image to
  388.     * @param  array   The attachment information
  389.     * @return object  The image mimePart object
  390.     * @access private
  391.     */
  392.     function &_addAttachmentPart(&$obj, $value){
  393.  
  394.         $params['content_type'] = $value['c_type'];
  395.         $params['encoding']     = $value['encoding'];
  396.         $params['disposition']  = 'attachment';
  397.         $params['dfilename']    = $value['name'];
  398.         $obj->addSubpart($value['body'], $params);
  399.     }
  400.  
  401.     /*
  402.     * Builds the multipart message from the list ($this->_parts) and
  403.     * returns the mime content.
  404.     *
  405.     * @param  array  Build parameters that change the way the email
  406.     *                is built. Should be associative. Can contain:
  407.     *                text_encoding  -  What encoding to use for plain text
  408.     *                                  Default is 7bit
  409.     *                html_encoding  -  What encoding to use for html
  410.     *                                  Default is quoted-printable
  411.     *                7bit_wrap      -  Number of characters before text is
  412.     *                                  wrapped in 7bit encoding
  413.     *                                  Default is 998
  414.     *                html_charset   -  The character set to use for html.
  415.     *                                  Default is iso-8859-1
  416.     *                text_charset   -  The character set to use for text.
  417.     *                                  Default is iso-8859-1
  418.     *                head_charset   -  The character set to use for headers.
  419.     *                                  Default is iso-8859-1
  420.     * @return string The mime content
  421.     * @access public
  422.     */
  423.     function &get($build_params = null)
  424.     {
  425.         if (isset($build_params)) {
  426.             while (list($key, $value) = each($build_params)) {
  427.                 $this->_build_params[$key] = $value;
  428.             }
  429.         }
  430.  
  431.         if (!empty($this->_html_images) AND isset($this->_htmlbody)) {
  432.             foreach ($this->_html_images as $value) {
  433.                 $this->_htmlbody = str_replace($value['name'], 'cid:'.$value['cid'], $this->_htmlbody);
  434.             }
  435.         }
  436.  
  437.         $null        = null;
  438.         $attachments = !empty($this->_parts)                ? TRUE : FALSE;
  439.         $html_images = !empty($this->_html_images)          ? TRUE : FALSE;
  440.         $html        = !empty($this->_htmlbody)             ? TRUE : FALSE;
  441.         $text        = (!$html AND !empty($this->_txtbody)) ? TRUE : FALSE;
  442.  
  443.         switch (TRUE) {
  444.             case $text AND !$attachments:
  445.                 $message =& $this->_addTextPart($null, $this->_txtbody);
  446.                 break;
  447.  
  448.             case !$text AND !$html AND $attachments:
  449.                 $message =& $this->_addMixedPart();
  450.  
  451.                 for ($i = 0; $i < count($this->_parts); $i++) {
  452.                     $this->_addAttachmentPart($message, $this->_parts[$i]);
  453.                 }
  454.                 break;
  455.  
  456.             case $text AND $attachments:
  457.                 $message =& $this->_addMixedPart();
  458.                 $this->_addTextPart($message, $this->_txtbody);
  459.  
  460.                 for ($i = 0; $i < count($this->_parts); $i++) {
  461.                     $this->_addAttachmentPart($message, $this->_parts[$i]);
  462.                 }
  463.                 break;
  464.  
  465.             case $html AND !$attachments AND !$html_images:
  466.                 if (isset($this->_txtbody)) {
  467.                     $message =& $this->_addAlternativePart($null);
  468.                        $this->_addTextPart($message, $this->_txtbody);
  469.                     $this->_addHtmlPart($message);
  470.  
  471.                 } else {
  472.                     $message =& $this->_addHtmlPart($null);
  473.                 }
  474.                 break;
  475.  
  476.             case $html AND !$attachments AND $html_images:
  477.                 if (isset($this->_txtbody)) {
  478.                     $message =& $this->_addAlternativePart($null);
  479.                     $this->_addTextPart($message, $this->_txtbody);
  480.                     $related =& $this->_addRelatedPart($message);
  481.                 } else {
  482.                     $message =& $this->_addRelatedPart($null);
  483.                     $related =& $message;
  484.                 }
  485.                 $this->_addHtmlPart($related);
  486.                 for ($i = 0; $i < count($this->_html_images); $i++) {
  487.                     $this->_addHtmlImagePart($related, $this->_html_images[$i]);
  488.                 }
  489.                 break;
  490.  
  491.             case $html AND $attachments AND !$html_images:
  492.                 $message =& $this->_addMixedPart();
  493.                 if (isset($this->_txtbody)) {
  494.                     $alt =& $this->_addAlternativePart($message);
  495.                     $this->_addTextPart($alt, $this->_txtbody);
  496.                     $this->_addHtmlPart($alt);
  497.                 } else {
  498.                     $this->_addHtmlPart($message);
  499.                 }
  500.                 for ($i = 0; $i < count($this->_parts); $i++) {
  501.                     $this->_addAttachmentPart($message, $this->_parts[$i]);
  502.                 }
  503.                 break;
  504.  
  505.             case $html AND $attachments AND $html_images:
  506.                 $message =& $this->_addMixedPart();
  507.                 if (isset($this->_txtbody)) {
  508.                     $alt =& $this->_addAlternativePart($message);
  509.                     $this->_addTextPart($alt, $this->_txtbody);
  510.                     $rel =& $this->_addRelatedPart($alt);
  511.                 } else {
  512.                     $rel =& $this->_addRelatedPart($message);
  513.                 }
  514.                 $this->_addHtmlPart($rel);
  515.                 for ($i = 0; $i < count($this->_html_images); $i++) {
  516.                     $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
  517.                 }
  518.                 for ($i = 0; $i < count($this->_parts); $i++) {
  519.                     $this->_addAttachmentPart($message, $this->_parts[$i]);
  520.                 }
  521.                 break;
  522.  
  523.         }
  524.  
  525.         if (isset($message)) {
  526.             $output = $message->encode();
  527.             $this->_headers = array_merge($this->_headers, $output['headers']);
  528.  
  529.             return $output['body'];
  530.  
  531.         } else {
  532.             return FALSE;
  533.         }
  534.     }
  535.  
  536.     /*
  537.     * Returns an array with the headers needed to prepend to the email
  538.     * (MIME-Version and Content-Type). Format of argument is:
  539.     * $array['header-name'] = 'header-value';
  540.     *
  541.     * @param  array $xtra_headers Assoc array with any extra headers. Optional.
  542.     * @return array Assoc array with the mime headers
  543.     * @access public
  544.     */
  545.     function &headers($xtra_headers = null)
  546.     {
  547.         // Content-Type header should already be present,
  548.         // So just add mime version header
  549.         $headers['MIME-Version'] = '1.0';
  550.         if (isset($xtra_headers)) {
  551.             $headers = array_merge($headers, $xtra_headers);
  552.         }
  553.         $this->_headers = array_merge($headers, $this->_headers);
  554.  
  555.         return $this->_encodeHeaders($this->_headers);
  556.     }
  557.  
  558.     /**
  559.     * Get the text version of the headers
  560.     * (usefull if you want to use the PHP mail() function)
  561.     *
  562.     * @param  array $xtra_headers Assoc array with any extra headers. Optional.
  563.     * @return string Plain text headers
  564.     * @access public
  565.     */
  566.     function txtHeaders($xtra_headers = null)
  567.     {
  568.         $headers = $this->headers($xtra_headers);
  569.         $ret = '';
  570.         foreach ($headers as $key => $val) {
  571.             $ret .= "$key: $val" . MAIL_MIME_CRLF;
  572.         }
  573.         return $ret;
  574.     }
  575.  
  576.     /**
  577.     * Sets the Subject header
  578.     * 
  579.     * @param  string $subject String to set the subject to
  580.     * access  public
  581.     */
  582.     function setSubject($subject)
  583.     {
  584.         $this->_headers['Subject'] = $subject;
  585.     }
  586.  
  587.     /**
  588.     * Set an email to the From (the sender) header
  589.     *
  590.     * @param string $email The email direction to add
  591.     * @access public
  592.     */
  593.     function setFrom($email)
  594.     {
  595.         $this->_headers['From'] = $email;
  596.     }
  597.  
  598.     /**
  599.     * Add an email to the Cc (carbon copy) header
  600.     * (multiple calls to this method is allowed)
  601.     *
  602.     * @param string $email The email direction to add
  603.     * @access public
  604.     */
  605.     function addCc($email)
  606.     {
  607.         if (isset($this->_headers['Cc'])) {
  608.             $this->_headers['Cc'] .= ", $email";
  609.         } else {
  610.             $this->_headers['Cc'] = $email;
  611.         }
  612.     }
  613.  
  614.     /**
  615.     * Add an email to the Bcc (blank carbon copy) header
  616.     * (multiple calls to this method is allowed)
  617.     *
  618.     * @param string $email The email direction to add
  619.     * @access public
  620.     */
  621.     function addBcc($email)
  622.     {
  623.         if (isset($this->_headers['Bcc'])) {
  624.             $this->_headers['Bcc'] .= ", $email";
  625.         } else {
  626.             $this->_headers['Bcc'] = $email;
  627.         }
  628.     }
  629.     
  630.     /**
  631.     * Encodes a header as per RFC2047
  632.     *
  633.     * @param  string  $input The header data to encode
  634.     * @return string         Encoded data
  635.     * @access private
  636.     */
  637.     function _encodeHeaders($input)
  638.     {
  639.         foreach ($input as $hdr_name => $hdr_value) {
  640.             preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $hdr_value, $matches);
  641.             foreach ($matches[1] as $value) {
  642.                 $replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
  643.                 $hdr_value = str_replace($value, '=?' . $this->_build_params['head_charset'] . '?Q?' . $replacement . '?=', $hdr_value);
  644.             }
  645.             $input[$hdr_name] = $hdr_value;
  646.         }
  647.         
  648.         return $input;
  649.     }
  650.  
  651. } // End of class
  652. ?>
  653.